iT邦幫忙

2021 iThome 鐵人賽

DAY 5
0
Modern Web

JavaScript學習日記系列 第 5

JavaScript學習日記 : Day5 - 基本型別(三)

  • 分享至 

  • xImage
  •  

1. 物件的引用

在討論物件引用前先探討call by value與call by reference的差別。

  • Primitive type(Boolean、String、Number、null、undefined) -- call by value
  • Objetc、Array、Function --- call by reference

1.1 Call by value

let message = "Hello!";
let phrase = message;

message = "Hello world!"

console.log(message); //Hello world
console.log(phrase); //Hello!


圖片來源: https://zh.javascript.info/object-copy

以上面為例子,把message指定成"Hello"時,message會在記憶體中儲存"Hello"(ex. 0x001),這時候把phrase指定為message,phrase會在記憶體中找到另一個獨立的位置(ex. 0x002)儲存"Hello",也就是說message與phrase是獨立的,不互相影響。

1.2 Call by reference

let user = {
  name: "John"
};

let admin = user;

admin.name = 'Peter';

console.log(user.name) // 'Peter'

當我們把user指定為一個Object時,user會在記憶體中找到一個位子(ex. 0x003),這時候user變數儲存的不是object,而是object的引用,此時把admin指定為user,這時候跟call by value不同的是admin不會獨立找一個記憶體位置,而是複製了user對於object的引用,所以當這個object變動時,所有有引用的變數都會受到影響。

2. 物件與數組的複製

2.1 數組

2.1.1 數組淺複製

主要依賴這兩個method會返回一個新的數組的特性:

let a = [1,2,3,4]
let b = a.slice(0)

console.log(a === b); // false

b.push(5); // a = [1,2,3,4]  b = [1,2,3,4,5]

2.1.2 數組深複製

深複製的方法皆適用於淺複製。

let a = [[0,0],[1,1]]
let b = Array.from(a)

a.push([2,2]) // a = [[0,0],[1,1],[2,2]] b = [[0,0],[1,1]]
  • 方法二 --- ES6展開符
let a = [[0,0],[1,1]]
let b = [...a]

a.push([2,2]) // a = [[0,0],[1,1],[2,2]] b = [[0,0],[1,1]]
let a = [[0,0],[1,1]];
let b = Object.assign([],a);

a.push([2,2]) // a = [[0,0],[1,1],[2,2]] b = [[0,0],[1,1]]
let a = [[0,0],[1,1]];
let b = JSON.parse(JSON.stringify(a));

a.push([2,2]) // a = [[0,0],[1,1],[2,2]] b = [[0,0],[1,1]]

2.2 物件

2.2.1 物件淺複製

  • 方法一 --- ES6展開符

展開符在array是深層複製,但是對於object來說是屬於淺複製,只有第一層是真正的複製,其他內層都是複製reference。

let person = {
    height:180,
    weight:70,
    score: {
        JavaScript: 100,
        PHP: 80,
        Python: 70
    }
}

let clonePerson = {...person}

clonePerson.height = 190; // person身高不受影響
clonePerson.score.Java = 60; // 深層的部分並沒有複製,所以會影響到person.score

與方法一相同,只有在第一層是真正有複製到。

let person = {
    height:180,
    weight:70,
    score: {
        JavaScript: 100,
        PHP: 80,
        Python: 70
    }
}

let clonePerson = Object.assign({},person)

clonePerson.height = 190; // person身高不受影響
clonePerson.score.Java = 60; // 深層的部分並沒有複製,所以會影響到person.score

2.2.2 物件深複製

let person = {
    height:180,
    weight:70,
    score: {
        JavaScript: 100,
        PHP: 80,
        Python: 70
    }
}

let clonePerson = JSON.parse(JSON.stringify(person));

clonePerson.height = 190; // person身高不受影響
clonePerson.score.Java = 60; // 深層的部分也有複製,所以一樣不會影響到person.score

參考資料:

談談 JavaScript 中 by reference 和 by value 的重要觀念
JavaScript Info
複製 Array / Object 的幾種常用方法(深/淺拷貝)


上一篇
JavaScript學習日記 : Day4 - 基本型別(二)
下一篇
JavaScript學習日記 : Day6 - 函數(一)
系列文
JavaScript學習日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言